home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / decoder.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-06  |  9.7 KB  |  447 lines

  1. #include "protocol.h"
  2. #include "bootinc.h"
  3.  
  4. /* Copyright 1993 Jamie Honan
  5.    May  be freely copied, sold, modified.
  6. */
  7.  
  8. /* #define NOLOAD */
  9. /* #define DEBUG */
  10.  
  11. typedef struct load_header
  12. {
  13.     unsigned long            magic;
  14.     unsigned char            hlength;
  15.     unsigned char            hflags1;
  16.     unsigned char            hflags2;
  17.     unsigned char            hflags3;
  18.     struct load_header far *    locn;
  19.     void   far *            execute;
  20.     char                dummy[494];    /* bring us up to 510 */
  21.     unsigned char            field55;
  22.     unsigned char            fieldAA;
  23. } LOAD_HEADER;
  24.  
  25. #define SKIP_LENGTH(u) (((u & 0xf)<<2) + ((u & 0xf0)>>2))
  26. #define OUR_LENGTH(u) ((u & 0xf)<<2)
  27.  
  28. typedef struct load_record
  29. {
  30.     unsigned char    rlength;
  31.     unsigned char    rtag1;
  32.     unsigned char    rtag2;
  33.     unsigned char    rflags;
  34.     unsigned long    address;
  35.     unsigned long    ilength;
  36.     unsigned long    mlength;
  37. }  LOAD_RECORD;
  38.  
  39. #define FLAG_B0        1
  40. #define FLAG_B1        2
  41.  
  42. #define FLAG_EOF    4
  43.  
  44. static LOAD_HEADER far *hptr;
  45. static LOAD_RECORD far *rptr;
  46.  
  47. #define    HOLE_END    0x100000
  48. #define    START_EXTD    0x100000
  49. #define HOLE_START    0x98000
  50.  
  51. #define LOWEST        0x10000
  52.  
  53. static int is_magic_format;
  54. static unsigned long datagoes;
  55. static unsigned long laststart;
  56. static unsigned long lastend;
  57. static unsigned long remaining;
  58. static void (far *execute_point) (void far *headp);
  59.  
  60. static unsigned long top_memory;
  61.  
  62. static EXTD_MOVE moveptr;
  63. static char *lastdata;
  64.  
  65. #ifdef NOLOAD
  66. char keepit[512];
  67. #endif
  68.  
  69. static void 
  70. prv(char *str)
  71. {
  72.     n_printf("%s datagoes %lx remaining %lx lastdata %x laststart %lx lastend %lx ",
  73.          str, datagoes, remaining, lastdata, laststart, lastend);
  74.     n_printf("rptr->flags %x\n", rptr->rflags);
  75. }
  76.  
  77. static int
  78. mem_range(unsigned long ptr, unsigned long len)
  79. {
  80.     /* can do anything, as long as they  don't write to it */
  81.     if (!len)
  82.         return 1;
  83.     if (ptr >= HOLE_START && ptr < HOLE_END)
  84.         return 0;
  85.     if (ptr < LOWEST)
  86.         return 0;
  87.     if (ptr >= top_memory)
  88.         return 0;
  89.     ptr += len;
  90.     if (ptr >= HOLE_START && ptr < HOLE_END)
  91.         return 0;
  92.     if (ptr > top_memory)
  93.         return 0;
  94.     return 1;
  95. }
  96.  
  97. static int
  98. mem_range86(void far *ptr, unsigned int len)
  99. {
  100. unsigned long v;
  101.  
  102.     v = far2long(ptr);
  103.     if (v + len >= HOLE_START)
  104.         return 0;
  105.     return mem_range(v, len);
  106. }
  107.  
  108. static int
  109. new_rptr()
  110. {
  111. unsigned long mem;
  112.  
  113. #ifdef DEBUG
  114.     prv("start rptr");
  115. #endif
  116.     if (OUR_LENGTH(rptr->rlength) < 16)
  117.     {
  118.         /* illegal */
  119.         return 3003;
  120.     }
  121.     mem = rptr->address;
  122.     if (rptr->rflags & FLAG_B1)
  123.     {
  124.         if (rptr->rflags & FLAG_B0)
  125.         {
  126.         /*   B0     B1
  127.                       1     1
  128.                       load address is subtracted from the start of
  129.                       the last image loaded. If the first image, then
  130.                       subtract from the start of where the 512 bytes were
  131.                       placed
  132.         */
  133.             if (mem > laststart)
  134.             {
  135.                 n_printf("Address %lx\n", rptr->address);
  136.                 return 3005; /* overflow */
  137.             }
  138.             mem = laststart - mem;
  139.         }
  140.         else
  141.         {
  142.         /*   B0     B1
  143.                       0     1
  144.                       subtract the load address from the one past the
  145.                       last writeable location in memory. Thus 1 would
  146.                       be the last location one could write in memory.
  147.         */
  148.             if (mem > top_memory)
  149.             {
  150.                 n_printf("Address %lx\n", rptr->address);
  151.                 return 3005; /* overflow */
  152.             }
  153.             mem = top_memory - mem;
  154.         }
  155.     }
  156.     else
  157.     {
  158.         if (rptr->rflags & FLAG_B0)
  159.         {
  160.         /*   B0     B1
  161.                       1     0
  162.                       add the load address to the location one past the last byte
  163.                       of the memory area required by the last image loaded.
  164.                       If the first image, then add to 512 plus the location
  165.                       where the 512 bytes were placed
  166.         */
  167.             mem += lastend;
  168.         }
  169.         else
  170.         {
  171.         /*   B0     B1
  172.                       0     0
  173.                       load address is an absolute 32 number
  174.         */
  175.         }
  176.     }
  177.     
  178.     if (!mem_range(mem, rptr->ilength))
  179.     {
  180.         n_printf("Address %lx\n", rptr->address);
  181.         /* illegal place to put things */
  182.         return 3002;
  183.     }
  184.     laststart = datagoes = mem;
  185.     lastend = laststart + rptr->mlength;
  186.     remaining = rptr->ilength;
  187.     n_printf(" %ld bytes (%ld blocks) at 0x%lx\n",
  188.             remaining, n_ldiv(remaining, 512), datagoes);
  189. #ifdef DEBUG
  190.     prv("end rptr");
  191. #endif
  192.     return 0;
  193. }
  194.  
  195.  
  196. int decode_header(void *ptr)
  197. {
  198. #ifdef TEST
  199.     top_memory = 0x740000L;
  200. #else
  201.     top_memory = n_mamount();
  202. #endif
  203.     if (top_memory)
  204.         top_memory = n_lmul(top_memory, 1024) + START_EXTD;
  205.     else
  206.         top_memory = HOLE_START;
  207.  
  208.     hptr =  MK_FP(segds(), ptr);
  209.     if (hptr->magic != 0x1B031336)
  210.     {
  211.         is_magic_format = 0;
  212.         if (hptr->field55 == 0x55 && hptr->fieldAA == 0xAA)
  213.         {
  214.             /*  can execute it */
  215. #ifndef NOLOAD
  216.             fmemcpy(MK_FP(0, 0x7c00), hptr, 512);
  217.             execute_point = MK_FP(0, 0x7c00);
  218. #endif
  219.             datagoes = LOWEST;
  220.             laststart = LOWEST;
  221.             if (top_memory > START_EXTD)
  222.             {
  223.                 remaining = top_memory
  224.                     - (HOLE_END - HOLE_START) - LOWEST;
  225.             }
  226.             else
  227.             {
  228.                 remaining = HOLE_START - LOWEST;
  229.             }
  230.             lastend = laststart + remaining;
  231.             return 0;
  232.         }
  233.         else
  234.         {
  235.             return 3000;
  236.         }
  237.     }
  238.     if (OUR_LENGTH(hptr->hlength) < 16)
  239.     {
  240.         /* illegal */
  241.         return 3001;
  242.     }
  243.     /* we have the magic number */
  244.     is_magic_format = 1;
  245.  
  246.     /* if we are dos, we can try to relocate the whole program
  247.        I don't like our chances
  248.      */
  249.     if (!mem_range86(hptr->locn, 512))
  250.     {
  251.         n_printf("Address %lp\n", hptr->locn);
  252.         /* attempt to place the 512 in an illegal place */
  253.         return 3002;
  254.     }
  255. #ifdef DEBUG
  256.     n_printf("Placing image header at %lp\n", hptr->locn);
  257.     n_printf("execute address is %lp\n", hptr->execute);
  258. #endif
  259. #ifdef NOLOAD
  260.     fmemcpy(MK_FP(segds(), keepit), hptr, 512);
  261.     hptr = MK_FP(segds(), keepit);
  262. #else
  263.     execute_point = hptr->execute;
  264.     fmemcpy(hptr->locn, hptr, 512);
  265.     hptr = hptr->locn;
  266. #endif
  267.     rptr = (LOAD_RECORD far *)(((char far *)hptr) + SKIP_LENGTH(hptr->hlength));
  268.     laststart = far2long(hptr);
  269.     lastend = laststart + 512;
  270.     return new_rptr();
  271. }
  272.  
  273. static int
  274. put_ext_data(unsigned long dest, char *data, int length)
  275. {
  276.     if (data != lastdata)
  277.     {
  278.         /* don't want to have to do this every time */
  279.         lastdata = data;
  280.         /* cheat */
  281.         *(unsigned long *)(&moveptr.s_segaddr[0]) = 
  282.             far2long(MK_FP(segds(), data));
  283.     }
  284.     /* cheat */
  285.     *(unsigned long *)(&moveptr.d_segaddr[0]) = dest;
  286.     moveptr.s_seglength = moveptr.d_seglength = length;
  287.     moveptr.s_access = moveptr.d_access = 0x93;
  288. #ifdef DEBUG
  289.     if (debug)
  290.         n_printf("Placing extended image data at %lx\n", dest);
  291.     return 0;
  292. #else
  293.     return n_lmove(&moveptr, (length + 1) / 2);
  294. #endif
  295. }
  296.  
  297. int
  298. place_data(char *data, int len)
  299. {
  300. int xlen;
  301. int v;
  302.  
  303.     while(len > 0)
  304.     {
  305.         xlen = len;
  306.         if (remaining == 0)
  307.         {
  308.             if (!is_magic_format)
  309.             {
  310.                 return 3004;
  311.             }
  312.             if (rptr->rflags & FLAG_EOF)
  313.                 return 3004;
  314.             rptr = (LOAD_RECORD far *)(((char far *)rptr) + SKIP_LENGTH(rptr->rlength));
  315.             v = new_rptr();
  316.             if (v)
  317.                 return v;
  318.             continue;
  319.         }
  320.         if (xlen > remaining)
  321.             xlen = remaining;
  322.         if (datagoes >= HOLE_START && datagoes < HOLE_END)
  323.         {
  324.             laststart = datagoes = HOLE_END;
  325.             /* doesn't have any meaning */
  326.             lastend = laststart + remaining;
  327.         }
  328.         if (datagoes < HOLE_START)
  329.         {
  330.             if (datagoes + xlen > HOLE_START)
  331.             {
  332.                 xlen = HOLE_START - datagoes;
  333.             }
  334. #ifdef DEBUG
  335.             if (debug)
  336.                 n_printf("Placing < 640K image data at %lx\n", datagoes);
  337. #endif
  338. #ifndef NOLOAD
  339.             lmemcpy(datagoes, data, xlen);
  340. #endif
  341.         }
  342.         else
  343.         {
  344.             v = put_ext_data(datagoes, data, xlen);
  345.             if (v)
  346.                 return 3010 + v;
  347.         }
  348.         data += xlen;
  349.         datagoes += xlen;
  350.         len -= xlen;
  351.         remaining -= xlen;
  352.     }
  353.     return 0;
  354. }
  355.  
  356. void warp_speed_Mr_spock(void)
  357. {
  358.     if (!execute_point)
  359.         return;
  360.     (*execute_point)(hptr);
  361. }
  362.  
  363. #ifdef TEST
  364.  
  365. long image[] = {
  366.           0x1B031336,  /* magic number */
  367.           0x4,         /* length of header is 16 bytes, no vendor info */
  368.           0x90000000,  /* location in ds:bx format */
  369.           0x90000200,  /* execute address in cs:ip format */
  370.  
  371.                        /* 2048 setup.S bytes */
  372.       0x4,           /* flags, not end, absolute address, 16 bytes this
  373.                           record, no vendor info */
  374.           0x90200,     /* load address - note format */
  375.           0x800,       /* 4 * 512 byte blocks for linux */
  376.           0x800,
  377.  
  378.                        /* kernel image */
  379.       0x4,           /* flags, not end, absolute address, 16 bytes this
  380.                           record, no vendor info */
  381.           0x10000,     /* load address - note format */
  382.           0x80000,     /* 512K (this could be shorter */
  383.           0x80000,
  384.  
  385.                        /* ramdisk for root file system */
  386.       0x04000004,  /* flags = last, absolute address, 16 bytes this
  387.                           record, no vendor info */
  388.           0x100000,    /* load address - in extended memory */
  389.           0x80000,     /* 512K for instance */
  390.           0x80000
  391.  
  392.     };
  393.  
  394. char zb[512];
  395.  
  396. long ls[128];
  397.  
  398. int testmove(unsigned long dest, char *data, int length)
  399. {
  400.     *(unsigned long *)(&moveptr.s_segaddr[0]) = 
  401.             far2long(MK_FP(segds(), data));
  402.     /* cheat */
  403.     *(unsigned long *)(&moveptr.d_segaddr[0]) = dest;
  404.     moveptr.s_seglength = moveptr.d_seglength = length;
  405.     moveptr.s_access = moveptr.d_access = 0x93;
  406.     return n_lmove(&moveptr, (length + 1) / 2);
  407. }
  408.  
  409. main()
  410. {
  411. int v;
  412. int x;
  413.  
  414.     n_printf("Test image stuff\n");
  415.     v = testmove(far2long(ls), image, sizeof(image));
  416.     n_printf("result %d\n", v);
  417.     for(v = 0; v < 12; v++)
  418.         n_printf("%d is %lx\n", v, ls[v]);
  419.     dos_exit(0);
  420.     
  421.     v = decode_header(image);
  422.     if (v)
  423.     {
  424.         netposterr(v);
  425.         dos_exit(1);
  426.     }
  427.     while (((v = place_data(zb, 512))) == 0)
  428.     {
  429.         x = monitor_check();
  430.         if (x)
  431.         {
  432.             if (x > 1)
  433.             {
  434.                 v = 2000;
  435.                 break;
  436.             }
  437.             prv("mon check");
  438.         }
  439.     }
  440.     prv("end proc");
  441.     netposterr(v);
  442.     dos_exit(0);
  443. }
  444.         
  445. #endif
  446.  
  447.